package com.ld.service.impl;

import com.ld.annotation.LdPermission;
import com.ld.doamin.Permission;
import com.ld.mapper.PermissionMapper;
import com.ld.service.IPermissionScanService;
import com.ld.basic.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class PermissionScanServiceImpl implements IPermissionScanService {
    @Value("${ld.scan.path}")
   private String packageName;

    @Autowired
    private PermissionMapper mapper;

    @Override
    public void scan() {
        //拿到所有的contoller类  只是权限定名  className:com.ronghuanet.controller.MainController
        List<Class> AllClass = ClassUtils.getAllClassName(packageName);

        //定义一个permission集合来装下面封装好的
        List<Permission> list=new ArrayList<>();
        //1 先判断类上面是否有自定义注解
        for (Class aClass : AllClass) {
            LdPermission annotation = (LdPermission) aClass.getAnnotation(LdPermission.class);
            if (Objects.isNull(annotation)){
                //如果是空的话就直接跳出本次循环
                continue;
            }
            //如果不是空的话就往下执行，先封装成一个permission对象，作为其他方法的parent
            Permission permission=new Permission();
            //设置name
            permission.setName(annotation.name());
            //设置描述
            permission.setDescs(annotation.desc());
            //还要设置url和sn  这些会用到@RequestMapping注解
            RequestMapping requestMapping = (RequestMapping) aClass.getAnnotation(RequestMapping.class);
            //严谨一点做个判断
            String parentUrl = requestMapping.value()[0];
            if (!Objects.isNull(parentUrl)){

                permission.setUrl(parentUrl);
            }
            //拿到类的名字作为父对象的唯一标识  要用getSimpleName才是类的直接名字
            permission.setSn(aClass.getSimpleName());

            //封装到集合中去，作为父权限
            list.add(permission);

            //封装好对象之后，拿到该类中的所有方法，并进行判断
            Method[] methods = aClass.getMethods();
            for (Method method : methods) {
                //一样的判断  先看看方法上有没有自定义注解
                LdPermission myMethod = method.getAnnotation(LdPermission.class);
                if (Objects.isNull(myMethod)){
                    continue;
                }
                //有注解的话 先定义一个权限对象来装
                Permission permission1=new Permission();
                //先把简单的设置上
                permission1.setName(myMethod.name());
                permission1.setDescs(myMethod.desc());

                //重点：  拼接url  需要用父的 加上自己@PostMapping之类里面的url
                 String url=getUrl(parentUrl,method);
                 permission1.setUrl(url);

                 //处理唯一标识 类名:方法名
                  permission1.setSn(aClass.getSimpleName()+":"+method.getName());

                  //还要封装父权限！！！！！！！！！！！！！
                permission1.setParent(permission);
                  list.add(permission1);
            }
        }

        //以上操作就把所有的带了自定义注解的对象封装成permission权限对象了，然后调用数据库去保存

        //先删除之前所有的权限，再重新去添加
        mapper.deleteAll();

        if (!CollectionUtils.isEmpty(list)){
            for (Permission permission : list) {
                mapper.add(permission);
            }
        }

    }

    /**
     * 处理url
     * @param parentUrl
     * @param method
     * @return
     */
    public String getUrl(String parentUrl,Method method){
        String url=parentUrl;
        GetMapping annotation = method.getAnnotation(GetMapping.class);
        if (!Objects.isNull(annotation)&& annotation.value().length > 0){
            url+=annotation.value()[0];
        }
        PostMapping annotation2 = method.getAnnotation(PostMapping.class);
        if (!Objects.isNull(annotation2)&& annotation2.value().length > 0){
            url+=annotation2.value()[0];
        }
        PutMapping annotation3 = method.getAnnotation(PutMapping.class);
        if (!Objects.isNull(annotation3)&& annotation3.value().length > 0){
            url+=annotation3.value()[0];
        }
        DeleteMapping annotation4 = method.getAnnotation(DeleteMapping.class);
        if (!Objects.isNull(annotation4)&& annotation4.value().length > 0){
            url+=annotation4.value()[0];
        }
        PatchMapping annotation5 = method.getAnnotation(PatchMapping.class);
        if (!Objects.isNull(annotation5)&& annotation5.value().length > 0){
            url+=annotation5.value()[0];
        }

        return url;
    }
}
